using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using ScrewTurn.Wiki;
using ScrewTurn.Wiki.PluginFramework;

namespace ScrewTurnWiki.Plugins.MahrEdv
{
    /// <summary>
    /// Usage: {listofcategories}
    /// 
    /// (Does the same thing as categorymenu, without listing the pages.)
    /// 
    /// The Plugin lists all categories in the current namespace as an
    /// unnumbered list. All entries are Links to the AllPages.aspx, so a click
    /// on a category will show the list of all pages that are part of it.
    /// 
    /// This can be used as a kind of auto-updating menu.
    /// 
    /// example:
    /// 
    /// - Category A
    /// - Category B
    /// 
    /// </summary>
    public class ListOfCategories : IFormatterProviderV30
    {
        private static readonly ComponentInformation info = new ComponentInformation("ListOfCategories", "Mahr EDV GmbH",
                                                                                     "1.0.0.1",
                                                                                     "http://www.mahr-edv.de",
                                                                                     "http://www.mahr-edv.de");

        private static readonly Regex CustomTagRegex = new Regex(@"{listofcategories}",
                                                                 RegexOptions.Compiled | RegexOptions.Singleline |
                                                                 RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);


        public void Init(IHostV30 host, string config)
        {
        }

        public string Format(string raw, ContextInformation context, FormattingPhase phase)
        {
            var buffer = new StringBuilder(raw);
            var block = FindAndRemoveFirstOccurrence(buffer);

            var sb = new StringBuilder();
            sb.Append("<ul>");

            var currentNamespace = Tools.DetectCurrentNamespaceInfo();

            var categories = Pages.GetCategories(currentNamespace);

            foreach (CategoryInfo t in categories)
            {
                sb.Append(@"<li>");
                sb.Append(@"<a href=""");
                UrlTools.BuildUrl(sb, "AllPages.aspx?Cat=", Tools.UrlEncode(t.FullName));
                sb.Append(@""">");
                sb.Append(NameTools.GetLocalName(t.FullName));
                sb.Append("</a>");
                sb.Append("</li>");
            }
            sb.Append("</ul>");

            if (block.Key != -1)
            {
                do
                {
                    buffer.Insert(block.Key, sb.ToString());
                    block = FindAndRemoveFirstOccurrence(buffer);
                } while (block.Key != -1);
            }

            return buffer.ToString();
        }


        private static KeyValuePair<int, string> FindAndRemoveFirstOccurrence(StringBuilder buffer)
        {
            Match match = CustomTagRegex.Match(buffer.ToString());

            if (match.Success)
            {
                buffer.Remove(match.Index, match.Length);

                return new KeyValuePair<int, string>(match.Index, match.Value);
            }

            return new KeyValuePair<int, string>(-1, null);
        }


        public bool PerformPhase1
        {
            get { return false; }
        }

        public bool PerformPhase2
        {
            get { return true; }
        }

        public bool PerformPhase3
        {
            get { return false; }
        }

        public int ExecutionPriority
        {
            get { return 50; }
        }

        public string PrepareTitle(string title, ContextInformation context)
        {
            return title;
        }

        public void Shutdown()
        {
        }

        public ComponentInformation Information
        {
            get { return info; }
        }

        public string ConfigHelpHtml
        {
            get { return null; }
        }

    }
}